﻿using System.Collections.Generic;
using System.Reflection;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Text.RegularExpressions;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif

/*
Unity通用2D游戏开发工具
本工具为 @漏了的水缸 个人制作并使用，未经允许请勿用于商业用途
*/

/*
该工具实现的功能：
：向量计算，随机数等常用功能
：对象池功能，帮助开发者简单的管理场景对象
: Resources资源操作，获取资源
：文件操作，存档读档操作
：按键重载，需要时直接修改Key值从而重定向按键输入
*/

/*
使用using static WaterCylinder;导入该工具
对象池功能在当前场景（scene）中含有名为Pool并装载了ObjectPools组件的对象时自动启用
*/


public class WaterCylinder : MonoBehaviour
{   
    #region 获取鼠标位置与触屏触摸位置
    ///获取鼠标位置与触屏触摸位置
    
    /// <summary>
    /// 获取鼠标位置。
    /// </summary>
    /// <returns></returns>
    public static Vector3 GetMousePosition(){
    	Vector3 MousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    	MousePosition.z = 0;
    	return MousePosition;
    }
    /// <summary>
    /// 获取鼠标平面位置。
    /// </summary>
    /// <returns></returns>
    public static Vector2 GetMousePosition2D(){
    	Vector2 MousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    	return MousePosition;
    }
    /// <summary>
    /// 获取指定ID触摸位置
    /// </summary>
    /// <param name="ID">触摸ID</param>
    /// <returns></returns>
    public static Vector3 GetTouchPosition(int ID){
        Vector3 pos = new Vector2(0,0);
        foreach(Touch touch in Input.touches){
            if(touch.fingerId == ID){
                pos = touch.position;
            }
        }
        pos.z = 0;
        return pos;
    }
    /// <summary>
    /// 获取指定ID触摸平面位置
    /// </summary>
    /// <param name="ID">触摸ID</param>
    /// <returns></returns>
    public static Vector2 GetTouchPosition2D(int ID){
        return Camera.main.ScreenToWorldPoint(Input.GetTouch(ID).position);
    }
    /// <summary>
    /// 当前最新按下时触摸ID
    /// </summary>
    public static int NewDownTouch = 0;
    /// <summary>
    /// 更新并获取当前最新按下时触摸ID
    /// </summary>
    /// <returns></returns>
    public static int GetNewDownTouch(){//最新的触摸点的ID
        if(Input.touchCount > 0){
            foreach(Touch t in Input.touches){
                if(t.phase == TouchPhase.Began){
                    NewDownTouch = t.fingerId;
                    return t.fingerId;
                }
            }
            return NewDownTouch;
        }else{
            return NewDownTouch;
        }
    }
    /// <summary>
    /// 当前最新松开时触摸ID
    /// </summary>
    public static int NewUpTouch = 0;
    /// <summary>
    /// 更新并获取当前最新松开时触摸ID
    /// </summary>
    /// <returns></returns>
    public static int GetNewUpTouch(){
        if(Input.touchCount > 0){
            foreach(Touch t in Input.touches){
                if(t.phase == TouchPhase.Ended){
                    NewUpTouch = t.fingerId;
                    return t.fingerId;
                }
            }
            return NewUpTouch;
        }else{
            return NewUpTouch;
        }
    }
    /// <summary>
    /// 是否有触摸按下
    /// </summary>
    /// <returns></returns>
    public static bool TouchDown(){
        if(Input.touchCount > 0){
            foreach(Touch t in Input.touches){
                if(t.phase == TouchPhase.Began){
                    return true;
                }
            }
            return false;
        }
        return false;
    }
    /// <summary>
    /// 是否有触摸松开
    /// </summary>
    /// <returns></returns>
    public static bool TouchUp(){
        if(Input.touchCount > 0){
            foreach(Touch t in Input.touches){
                if(t.phase == TouchPhase.Ended){
                    return true;
                }
            }
            return false;
        }
        return false;
    }
    
    #endregion

    #region 场景操作

    /// <summary>
    /// 切换（加载）场景
    /// </summary>
    /// <param name="name"></param>
    public static void ChangeScene(string name){
        SceneManager.LoadScene(name);
    }
    /// <summary>
    /// 获取当前场景
    /// </summary>
    /// <returns></returns>
    public static string SceneNow(){
        string s = SceneManager.GetActiveScene().name;
        return s;
    }

    #endregion

    #region 物体操作

    //获取子物体

    /// <summary>
    /// 通过Tag获取子物体，获取第一个。
    /// </summary>
    /// <param name="obj">父物体</param>
    /// <param name="tag">Tag</param>
    /// <returns></returns>
    public static GameObject FindChildByTag(GameObject obj, string tag){
        foreach(Transform item in obj.transform){
            if(item.gameObject.tag == tag)return item.gameObject;
        }
        return null;
    }
    /// <summary>
    /// 通过名字获取子物体。
    /// </summary>
    /// <param name="obj">父物体</param>
    /// <param name="name">Tag</param>
    /// <returns></returns>
    public static GameObject FindChildByName(GameObject obj, string name){
        foreach(Transform item in obj.transform){
            if(item.gameObject.name == name)return item.gameObject;
        }
        return null;
    }

    //物体生成与销毁

    /// <summary>
    /// <para>通过prefab生成物体到当前场景中，</para>
    /// <para>场景中有Pool物体时将生成的物体存储到对象池中。</para>
    /// </summary>
    /// <param name="prefab"></param>
    /// <returns></returns>
    public static GameObject Creat(GameObject prefab){
        GameObject obj = Instantiate(prefab) as GameObject;

        //对象池功能
        GameObject pools_obj;
        if(pools_obj = GameObject.Find("Pool")){
            ObjectPools pools = pools_obj.GetComponent<ObjectPools>();
            pools.Add(obj);
        }

        return obj;
    }
    /// <summary>
    /// <para>销毁指定的物体，</para>
    /// <para>场景中有Pool物体时将指定的物体从对象池中移除。</para>
    /// </summary>
    /// <param name="prefab"></param>
    /// <returns></returns>
    public static bool Delete(GameObject obj){//销毁物体
        if(obj){

            //对象池功能
            GameObject pools_obj;
            if(pools_obj = GameObject.Find("Pool")){
                ObjectPools pools = pools_obj.GetComponent<ObjectPools>();
                pools.Del(obj);
            }

            Destroy(obj);
            return true;
        }else{
            Debug.Log("删除无效");
            return false;
        }
    }

    /// <summary>
    /// <para>通过prefab和生成位置生成物体到当前场景中，</para>
    /// <para>场景中有Pool物体时将生成的物体存储到对象池中。</para>
    /// </summary>
    /// <param name="prefab"></param>
    /// <param name="position"></param>
    /// <returns></returns>
    public static GameObject Creat(GameObject prefab, Vector2 position){//在位置上创建物体
        GameObject obj = Creat(prefab);
        obj.GetComponent<Transform>().position = position;
        return obj;   
    }
    /// <summary>
    /// <para>通过prefab和父对象及相对位置生成物体到当前场景中，</para>
    /// <para>场景中有Pool物体时将生成的物体存储到对象池中。</para>
    /// </summary>
    /// <param name="prefab"></param>
    /// <param name="parent"></param>
    /// <param name="localPosition"></param>
    /// <returns></returns>
    public static GameObject Creat(GameObject prefab, Transform parent, Vector2 localPosition){//在相对位置上创建物体
        GameObject obj = Creat(prefab);
        obj.GetComponent<Transform>().parent = parent;
        obj.GetComponent<Transform>().localPosition = localPosition;
        return obj;
    }
    
    #endregion

    #region 向量计算

    /// <summary>
    /// 默认为上方向的旋转
    /// </summary>
    /// <param name="angle"></param>
    /// <returns></returns>
    public static Vector2 Rotate(float angle){//默认为上方向的旋转
        float tx = Mathf.Sin(angle*Mathf.Deg2Rad);
        float ty = Mathf.Cos(angle*Mathf.Deg2Rad);
        return new Vector2(tx,ty);
    }
    /// <summary>
    /// 自定义基础向量的旋转
    /// </summary>
    /// <param name="toward"></param>
    /// <param name="angle"></param>
    /// <returns></returns>
    public static Vector2 Rotate(Vector2 toward, float angle){//自定义基础向量
        float tx = toward.x*Mathf.Cos(angle*Mathf.Deg2Rad)+toward.y*Mathf.Sin(angle*Mathf.Deg2Rad);
        float ty = -toward.x*Mathf.Sin(angle*Mathf.Deg2Rad)+toward.y*Mathf.Cos(angle*Mathf.Deg2Rad);
        return new Vector2(tx,ty);
    }
    /// <summary>
    /// 从向量Begin到End的角度，含有正负。
    /// </summary>
    /// <param name="begin"></param>
    /// <param name="end"></param>
    /// <returns></returns>
    public static float Angle(Vector2 begin, Vector2 end){//从向量Begin到End的角度，含有正负。
        float angle = Vector2.Angle(begin, end);
        Vector3 cross = Vector3.Cross(begin, end);
        if(cross.z > 0)return angle;
        else return -angle;
    }

    //随机数生成器

    /// <summary>
    /// 生成a-b之间的随机数，不包含ab。
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static float Range(float a, float b){
        UnityEngine.Random.InitState((int)System.DateTime.Now.Ticks);
        return UnityEngine.Random.Range(a,b);
    }
    
    /// <summary>
    /// 获取两个向量的中间向量
    /// </summary>
    /// <param name="begin"></param>
    /// <param name="end"></param>
    /// <param name="rate">中间向量相对位置的比例</param>
    /// <returns></returns>
    public static Vector2 Lerp(Vector2 begin, Vector2 end, float rate = 0.5f){
        Vector2 os = (end - begin) * rate;
        return begin + os;
    }

    /// <summary>
    /// 检查两个向量是否接近
    /// </summary>
    /// <param name="begin"></param>
    /// <param name="end"></param>
    /// <param name="rate"></param>
    /// <returns></returns>
    public static bool Approach(Vector2 begin, Vector2 end, float rate = 0.01f){
        return Vector2.Distance(begin, end) < rate;
    }
    
    /// <summary>
    /// 检查两个浮点数是否接近
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <param name="rate"></param>
    /// <returns></returns>
    public static bool Approach(float a, float b, float rate = 0.01f){
        return Mathf.Abs(a - b) < rate;
    }

    #endregion

    #region 获取资源

    public static Dictionary<string, UnityEngine.Object> _resources = new Dictionary<string, UnityEngine.Object>();
    
    /// <summary>
    /// 从Resources文件夹里加载资源
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_name"></param>
    /// <returns></returns>
    public static T GetResources<T>(string _name) where T : UnityEngine.Object{
        lock(_resources)if(!_resources.ContainsKey(_name)){
            T obj = Resources.Load(_name) as T;
            _resources.Add(_name, obj);
        }
        lock(_resources)if(_resources[_name] == null){
            _resources[_name] = Resources.Load<T>(_name);
        }
        lock(_resources)if(_resources[_name] != null){
            return _resources[_name] as T;
        }else{
            return null;
        }
        
    }
    /// <summary>
    /// 从Resources文件夹里异步加载资源
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_name"></param>
    /// <returns>异步包，可以获取资源加载结果以及加载进度</returns>
    public static ResourceRequest LoadResourceAsync<T>(string _name) where T : UnityEngine.Object{
        ResourceRequest q = Resources.LoadAsync<T>(_name);
        q.completed += (a) => {
            if(a.isDone){
                T obj = (T) q.asset;
                lock(_resources)if(_resources.ContainsKey(_name)){
                    _resources[_name] = obj;
                }else{
                    _resources.Add(_name, obj);
                }
            }
        };
        return q;
    }

    /// <summary>
    /// 释放所有资源
    /// </summary>
    public static void UnLoadResources(){
        foreach(KeyValuePair<string, UnityEngine.Object> item in _resources){
            Resources.UnloadAsset(item.Value);
        }
    }
    
    /// <summary>
    /// 从Resources中加载prefab。
    /// </summary>
    /// <param name="_name"></param>
    /// <returns></returns>
    public static GameObject GetPrefab(string _name){
        return GetResources<GameObject>(_name);
    }
    /// <summary>
    /// 从Resources中异步加载物体资源，加载成功的资源可以使用GetPrefab获取
    /// </summary>
    /// <param name="_name"></param>
    /// <returns>异步包，可以获取资源加载结果以及加载进度</returns>
    public static ResourceRequest LoadPrefabAsync(string _name){
        return LoadResourceAsync<GameObject>(_name);
    }
    /// <summary>
    /// 从Resources中加载精灵图片。
    /// </summary>
    /// <param name="_name"></param>
    /// <returns></returns>
    public static Sprite GetSprite(string _name){
        return GetResources<Sprite>(_name);
    }
    /// <summary>
    /// 从Resources中异步加载精灵资源，加载成功的资源可以使用GetSprite获取
    /// </summary>
    /// <param name="_name"></param>
    /// <returns>异步包，可以获取资源加载结果以及加载进度</returns>
    public static ResourceRequest LoadSpriteAsync(string _name){
        return LoadResourceAsync<Sprite>(_name);
    }

    /// <summary>
    /// 释放所有未使用的资源
    /// </summary>
    public static void UnLoadAllResources(){
        Resources.UnloadUnusedAssets();
    }

    #endregion

    #region 矩形相关

    /// <summary>
    /// 计算点是否在矩阵里（仅计算二维坐标）。
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="rect"></param>
    /// <returns></returns>
    public static bool PosInRect(Vector2 pos, Rect rect){
        if(pos.x > rect.x + rect.width / 2
        || pos.x < rect.x - rect.width / 2
        || pos.y > rect.y + rect.height / 2
        || pos.y < rect.y - rect.height / 2){
            return false;
    }else{
            return true;
        }
    }

    #endregion

    #region Sprite与Texture2D相互转化

    /// <summary>
    /// 将sprite转化为texture
    /// </summary>
    /// <param name="sprite"></param>
    /// <returns></returns>
    public static Texture2D Sprite2Texture2D(Sprite sprite){
        Texture2D t2d = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
        var pixels = sprite.texture.GetPixels(
            (int)sprite.textureRect.x,
            (int)sprite.textureRect.y,
            (int)sprite.textureRect.width,
            (int)sprite.textureRect.height);
        t2d.SetPixels(pixels);
        t2d.Apply();
        return t2d;
    }

    /// <summary>
    /// 将texture2D转化为sprite
    /// </summary>
    /// <param name="t2d"></param>
    /// <returns></returns>
    public static Sprite Texture2D2Sprite(Texture2D t2d){
        Sprite s= Sprite.Create(t2d, new Rect(0, 0, t2d.width, t2d.height), Vector2.zero);
        return s;
    }

    #endregion

    #region 文件操作

    /// <summary>
    /// 读取文件
    /// </summary>
    /// <param name="path"></param>
    /// <returns>文件字符流对象</returns>
    public static StreamReader FileRead(string path){//读取文件
        if(File.Exists(path)){
            return new StreamReader(path);
        }else{
            return null;
        }
    }
    /// <summary>
    /// 从个人用户目录读取文件（C:\user\）
    /// </summary>
    /// <param name="path"></param>
    /// <returns>文件字符流对象</returns>
    public static StreamReader FileReadPersistent(string path){//从个人用户目录读取文件（C盘固定路径）
        if(File.Exists(Application.persistentDataPath + "/" + path)){
            return new StreamReader(Application.persistentDataPath + "/" + path);
        }else{
            return null;
        }
    }
    /// <summary>
    /// 写入文件
    /// </summary>
    /// <param name="path"></param>
    /// <returns>文件字符流对象</returns>
    public static StreamWriter FileWrite(string path){
        if(File.Exists(path)){
            return new StreamWriter(path);
        }else{
            return null;
        }
    }
    /// <summary>
    /// 从个人用户目录写入文件（C:\user\）
    /// </summary>
    /// <param name="path"></param>
    /// <returns>文件字符流对象</returns>
    public static StreamWriter FileWritePersistent(string path){
        if(File.Exists(Application.persistentDataPath + "/" + path)){
            return new StreamWriter(Application.persistentDataPath + "/" + path);
        }else{
            return null;
        }
    }

    /// <summary>
    /// 读取文件的所有内容
    /// </summary>
    /// <param name="reader"></param>
    /// <returns>文件内容字符串</returns>
    public static string ReadAll(StreamReader reader){
        string str = "";
        if(reader != null){
            str = reader.ReadToEnd();
            reader.Close();
        }
        return str;
    }
    /// <summary>
    /// 读取文件的所有内容
    /// </summary>
    /// <param name="path"></param>
    /// <returns>文件内容字符串</returns>
    public static string ReadAll(string path){
        StreamReader reader = FileRead(path);
        return ReadAll(reader);
    }
    /// <summary>
    /// 从个人用户目录下的文件中读取所有内容
    /// </summary>
    /// <param name="path"></param>
    /// <returns>文件内容字符串</returns>
    public static string ReadAllPersistent(string path){
        StreamReader reader = FileReadPersistent(path);
        return ReadAll(reader);
    }

    /// <summary>
    /// 写入文件内容
    /// </summary>
    /// <param name="writer"></param>
    /// <param name="str">写入内容</param>
    /// <returns>是否写入成功</returns>
    public static bool WriteAll(StreamWriter writer, string str){
        if(writer != null){
            writer.Write(str);
            writer.Close();
            return true;
        }else{
            return false;
        }
    }
    /// <summary>
    /// 写入文件内容
    /// </summary>
    /// <param name="path"></param>
    /// <param name="str">写入内容</param>
    /// <returns>是否写入成功</returns>
    public static bool WriteAll(string path, string str){
        StreamWriter writer = FileWrite(path);
        return WriteAll(writer, str);
    }
    /// <summary>
    /// 写入内容到个人用户目录下的文件
    /// </summary>
    /// <param name="path">写入内容</param>
    /// <param name="str"></param>
    /// <returns>是否写入成功</returns>
    public static bool WriteAllPersistent(string path, string str){
        StreamWriter writer = FileWritePersistent(path);
        return WriteAll(writer, str);
    }

    #endregion

    #region 鼠标输入

    /// <summary>
    /// 左键按下
    /// </summary>
    /// <returns></returns>
    public static bool InputOperaDown{
        get{
            if(Input.GetMouseButtonDown(0))return true;
            else return false;
        }
    }
    /// <summary>
    /// 左键按住
    /// </summary>
    /// <returns></returns>
    public static bool InputOpera{
        get{
            if(Input.GetMouseButton(0))return true;
            else return false;
        }
    }
    /// <summary>
    /// 左键弹起
    /// </summary>
    /// <returns></returns>
    public static bool InputOperaUp{
        get{
            if(Input.GetMouseButtonUp(0))return true;
            else return false;
        }
    }
    /// <summary>
    /// 右键按下
    /// </summary>
    /// <returns></returns>
    public static bool InputChoiceDown{
        get{
            if(Input.GetMouseButtonDown(1))return true;
            else return false;
        }
    }
    /// <summary>
    /// 右键按住
    /// </summary>
    /// <returns></returns>
    public static bool InputChoice{
        get{
            if(Input.GetMouseButton(1))return true;
            else return false;
        }
    }
    /// <summary>
    /// 右键谈起
    /// </summary>
    /// <returns></returns>
    public static bool InputChoiceUp{
        get{
            if(Input.GetMouseButtonUp(1))return true;
            else return false;
        }
    }
    /// <summary>
    /// 滚轮上
    /// </summary>
    /// <returns></returns>
    public static bool InputWheelUp{
        get{
            if(Input.GetAxis("Mouse ScrollWheel") > 0)return true;
            else return false;
        }
    }
    /// <summary>
    /// 滚轮下
    /// </summary>
    /// <returns></returns>
    public static bool InputWheelDown{
        get{
            if(Input.GetAxis("Mouse ScrollWheel") < 0)return true;
            else return false;
        }
    }
    
    #endregion

    #region 键盘输入

    /// <summary>
    /// 左键按键
    /// </summary>
    public static string KeyLeft = "a";
    /// <summary>
    /// 右键按键
    /// </summary>
    public static string KeyRight = "d";
    /// <summary>
    /// 上键按键
    /// </summary>
    public static string KeyUp = "w";
    /// <summary>
    /// 下键按键
    /// </summary>
    public static string KeyDown = "s";
    /// <summary>
    /// 重新装填按键
    /// </summary>
    public static string KeyChange = "r";
    /// <summary>
    /// 跳跃按键
    /// </summary>
    public static string KeyBurst = "space";

    

    //键盘方向键输入队列

    /// <summary>
    /// 方向键输入列表
    /// </summary>
    public static List<string> KeyList = new List<string>();

    /*
    输入队列的队列尾部的值是最后输入
    */
    /// <summary>
    /// 获取方向键输入，输入结果存入输入列表中
    /// </summary>
    public static void InputKeyList(){//输入队列，放在Update里以持续进行队列运算
        if(InputLeftDown)KeyList.Add(KeyLeft);
        if(InputRightDown)KeyList.Add(KeyRight);
        if(InputUpDown)KeyList.Add(KeyUp);
        if(InputDownDown)KeyList.Add(KeyDown);

        if(InputLeftUp)KeyList.Remove(KeyLeft);
        if(InputRightUp)KeyList.Remove(KeyRight);
        if(InputUpUp)KeyList.Remove(KeyUp);
        if(InputDownUp)KeyList.Remove(KeyDown);

        //输入补正
        if(InputLeft){
            if(!KeyList.Contains(KeyLeft)){
                KeyList.Add(KeyLeft);
            }
        }else{
            if(KeyList.Contains(KeyLeft)){
                KeyList.Remove(KeyLeft);
            }
        }
        if(InputRight){
            if(!KeyList.Contains(KeyRight)){
                KeyList.Add(KeyRight);
            }
        }else{
            if(KeyList.Contains(KeyRight)){
                KeyList.Remove(KeyRight);
            }
        }
        if(InputUp){
            if(!KeyList.Contains(KeyUp)){
                KeyList.Add(KeyUp);
            }
        }else{
            if(KeyList.Contains(KeyUp)){
                KeyList.Remove(KeyUp);
            }
        }
        if(InputDown){
            if(!KeyList.Contains(KeyDown)){
                KeyList.Add(KeyDown);
            }
        }else{
            if(KeyList.Contains(KeyDown)){
                KeyList.Remove(KeyDown);
            }
        }
    }

    /// <summary>
    /// 获取倒数第id个key的值，放在Update里以持续进行队列运算
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public static string GetKeyInList(int id){//获取倒数第id个key的值，放在Update里以持续进行队列运算
        InputKeyList();
        string key = "";
        if(KeyList.Count - id >= 0)
            key = KeyList[KeyList.Count - id];
        return key;
    }

    /// <summary>
    /// 获取四方向方向输入结果。
    /// </summary>
    /// <returns></returns>
    public static Vector2 GetStraight(){//获取直边
        string key = GetKeyInList(1);
        Vector2 velocity = new Vector2(0,0);
        if(key != ""){
            if(key == KeyUp){
                velocity = new Vector2(0,1);
            }else if(key == KeyDown){
                velocity = new Vector2(0,-1);
            }else if(key == KeyLeft){
                velocity = new Vector2(-1,0);
            }else if(key == KeyRight){
                velocity = new Vector2(1,0);
            }
        }
        return velocity;
    }

    /// <summary>
    /// 获取八方向方向输入结果。
    /// </summary>
    /// <returns></returns>
    public static Vector2 GetOblique(){//获取斜边。2D移动的终极解决方案，直接放在Updata里就能获得当前准确的velocity
        string key = GetKeyInList(1);
        Vector2 velocity = GetStraight();
        if(KeyList.Count >= 2 && key != ""){
            for(int i = KeyList.Count - 2; i >= 0; i--){
                key = KeyList[i];
                if(velocity.x != 0){
                    if(key == KeyUp){
                        velocity.y = 1;
                        break;
                    }else if(key == KeyDown){
                        velocity.y = -1;
                        break;
                    }
                }else if(velocity.y != 0){
                    if(key == KeyRight){
                        velocity.x = 1;
                        break;
                    }else if(key == KeyLeft){
                        velocity.x = -1;
                        break;
                    }
                }
            }
        }
        return velocity;
    }


    //键盘输入
    

    public static bool InputLeftDown{
        get{
            if(Input.GetKeyDown(KeyLeft))return true;
            else return false;
        }
    }
    public static bool InputLeft{
        get{
            if(Input.GetKey(KeyLeft))return true;
            else return false;
        }
    }
    public static bool InputLeftUp{
        get{
            if(Input.GetKeyUp(KeyLeft))return true;
            else return false;
        }
    }
    public static bool InputRightDown{
        get{
            if(Input.GetKeyDown(KeyRight))return true;
            else return false;
        }
    }
    public static bool InputRight{
        get{
            if(Input.GetKey(KeyRight))return true;
            else return false;
        }
    }
    public static bool InputRightUp{
        get{
            if(Input.GetKeyUp(KeyRight))return true;
            else return false;
        }
    }
    public static bool InputDownDown{
        get{
            if(Input.GetKeyDown(KeyDown))return true;
            else return false;
        }
    }
    public static bool InputDown{
        get{
            if(Input.GetKey(KeyDown))return true;
            else return false;
        }
    }
    public static bool InputDownUp{
        get{
            if(Input.GetKeyUp(KeyDown))return true;
            else return false;
        }
    }
    public static bool InputUpDown{
        get{
            if(Input.GetKeyDown(KeyUp))return true;
            else return false;
        }
    }
    public static bool InputUp{
        get{
            if(Input.GetKey(KeyUp))return true;
            else return false;
        }
    }
    public static bool InputUpUp{
        get{
            if(Input.GetKeyUp(KeyUp))return true;
            else return false;
        }
    }
    public static bool InputChangeWeapon{
        get{
            if(Input.GetKeyUp(KeyChange))return true;
            else return false;
        }
    }
    public static bool InputBurstDown{
        get{
            if(Input.GetKeyDown(KeyBurst))return true;
            else return false;
        }
    }
    public static bool InputBurst{
        get{
            if(Input.GetKey(KeyBurst))return true;
            else return false;
        }
    }
    public static bool InputBurstUp{
        get{
            if(Input.GetKeyUp(KeyBurst))return true;
            else return false;
        }
    }

    #endregion

    #region 存档
    
    /// <summary>
    /// 存储数据到指定容器
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="target">容器名称</param>
    /// <param name="data"></param>
    public static void SaveSet<T>(string target, T data){
        object _data = data;
        if(data is int){
            PlayerPrefs.SetInt(target, (int)_data);
        }else if(data is float){
            PlayerPrefs.SetFloat(target, (float)_data);
        }else if(data is string){
            PlayerPrefs.SetString(target, (string)_data);
        }
    }
    /// <summary>
    /// 从指定的容器里读取数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="target">容器名称</param>
    /// <returns></returns>
    public static object SaveGet<T>(string target){
        T data = default;
        object _data = data;
        if(_data is int){
            _data = PlayerPrefs.GetInt(target);
        }else if(_data is float){
            _data = PlayerPrefs.GetFloat(target); 
        }else if(_data is string){
            _data = PlayerPrefs.GetString(target); 
        }
        return _data;
    }

    #endregion

    #region 编辑器相关
    
    #if UNITY_EDITOR
    /// <summary>
    /// 获取操作的属性对象
    /// </summary>
    /// <param name="property"></param>
    /// <returns></returns>
    public static object GetProperty(SerializedProperty property){
        try{
            object value = property.serializedObject.targetObject;
            string[] names = property.propertyPath.Split(".");
            
            Type type = value.GetType();
            FieldInfo info = type.GetField(names[0]);
            
            foreach(string name in names){
                
                if(name.Contains("data")){
                    
                    Match match = Regex.Match(name, @"data\[([^\]]+)\]");
                    int id = int.Parse(match.Groups[1].Value);
                    PropertyInfo pinfo = type.GetProperty("Item");
                    value = pinfo.GetValue(value, new object[]{id});
                    type = value.GetType();
                    
                }else if(name.Contains("Array")){
                    
                    continue;//Array不是一个有效的路径
                    
                }else{
                    
                    info = type.GetField(name);
                    value = info.GetValue(value);
                    type = value.GetType();
                    
                }
                
            }
            return value;
        }catch(Exception e){
            Debug.LogError(e);
            return null;
        }
    }   
    
    #endif

    #endregion
}


//流程类，附带单例效果。
/*
这是个父类，游戏流程直接继承该类即可，继承方式为：
class Game: Process<Game>
使用方法：
一：含有Instance单例，外部对象可直接访问。
二：流程控制中枢：
    在子类里定义名为“Process” + 流程序号的方法,即可。列如：
    void process1{
        Next();
    }
    void process2{
        Next();
    }
    在方法中使用Next()来跳转到下一个流程，或者使用Next(int)跳转到指定流程。
    Wait(float, function=)方法可以暂停检测，指定时间之后跳转到下一个流程,也可以一段时间后运行特定方法。
    流程方法的最后添加End()。
    暂时就这些功能。

需要注意的是，Process后的数字和Global.A是对应的。
*/
/*
public class GameProcess<T> : MonoBehaviour where T: GameProcess<T>, new()
{
    static T instance;
    public static T Instance{
        get{
            if(instance == null)instance = FindObjectOfType<T>() as T;
            return instance;
        }
    }

    public bool pause = false;

    public bool processEnd = true;

    public int a = 0;

    //不删除功能，暂时不用
   /* void Awake(){
        DontDestroyOnLoad(this);
        if(FindObjectOfType<T>() != this){
           Unity2dGeneralDevelopmentTool.Delete(this.gameObject);
        }
    }*//*
/*
    protected void Next(){
        a = a + 1;
        End();
        pause = false;
    }
    protected void Next(int target){
        a = target;
        End();
        pause = false;
    }
    protected void End(){
        processEnd = true;
        Global.A = a;
    }
    protected void Wait(float time, string function = ""){
        if(!pause){
            pause = true;
            if(function == ""){
                Invoke("Next", time);
            }else{
                Invoke(function, time);
            }
            
        }
    }

    protected int process(){
        a = Global.A;
        if(processEnd && !pause){
            processEnd = false;
            Invoke("Process" + a, 0);
        }
        return a;
    }

    void Update(){
        process();
    }
}
*/